Threaded programming environments, where several independent sequences of instructions execute concurrently within a shared memory space, provide a powerful paradigm for addressing several types of computational problems and for using multiprocessor systems efficiently. However, the shared memory space also makes possible a type of programming error that does not affect single-threaded programs that execute in a private, virtual memory space. Since threads can access (and modify) each other's memory, software developers must use great caution when passing values between threads by reference, lest such references inadvertently be used by a thread after the original variable or memory structure has become invalid.
As a concrete example, consider a first thread executing a subroutine that uses a local variable. The local variable will probably reside in a portion of memory dedicated to the first thread's stack. The first thread may provide the address of the local variable to a second thread so that the second thread can examine or modify the variable. However, if the first thread exits the subroutine, the local variable will go out of scope and the memory it occupied on the first thread's stack will likely be re-used for a different subroutine's stack frame. If the second thread now accesses the memory that previously held the local variable, it will probably obtain unexpected or incorrectly-formatted data; if it modifies the memory, it will probably cause incorrect or erratic operation of the first thread.
Although it is possible for correctly-designed threaded programs to access memory of one thread's stack from a different thread, the challenges of ensuring the validity of such cross-thread stack access (particularly in a large, complex program) may outweigh any advantages of doing so. For this reason, some software design rules prohibit cross-thread access, while others call for identification and careful review of any accesses.
Threaded programming environments have another characteristic that can complicate the development and debugging of multi-threaded programs. Threaded systems commonly lack an implicit thread synchronization mechanism: thread execution may proceed piecemeal on a timesliced basis, or threads may execute simultaneously on multiple processors of a multi-processor system. The precise order and temporal relationship between thread operations may vary from run to run and from system to system. Any synchronization that is logically required by the program must be explicitly coded using primitives such as mutexes, events, and semaphores, but except for these points of synchronization, there is often no guarantee that one operation will happen before or after another. The indeterminate temporal relationship between some thread operations makes analysis of thread memory use difficult. A method of determining whether certain operations will always occur after other operations may serve as the basis of a useful analytical tool for software developers.